package juegos;

import java.util.Vector;


/**
 * 
 * @author DaNieLooP
 *
 */
public class NodoFichas extends Nodo{
	/**
	 * tablero de juego
	 */
	private int tablero[]=new int[7];
	/**
	 * posicion del hueco
	 */
	private int x;
	
	/**
	 * constructora por defecto
	 */
	public NodoFichas(){
		this.informado=true;
		tablero[0]=1;tablero[1]=1;tablero[2]=1;
		tablero[3]=0;tablero[4]=2;tablero[5]=2;
		tablero[6]=2;
		//hueco en el medio
		this.x=3;
		this.coste=0;
		this.profundidad=0;
		this.camino="Estado inicial, ";
		calculaHeur();
		calculaEstado();		
	}
	
	/**
	 * constructora con parametros
	 * @param tab tablero de juego
	 * @param c posicion del juego
	 * @param op operador a usar
	 * @param cam camino hasta el nodo
	 * @param valor valor del nodo
	 * @param coste acumulado hasta el nodo
	 * @param prof profundidad del nodo
	 */
	public NodoFichas(int []tab,int c,int op,String cam,int valor,int coste,int prof){
		this.informado=true;
		for (int i=0;i<7;i++)
			tablero[i]=tab[i];
		this.coste=valor + coste;
		this.profundidad=prof+1;
		x=c;
		String mov;
		switch (op){
		case 1: mov = (" Izquierda 1,"); break;
		case 2: mov = (" Derecha 1,"); break;
		case 3: mov = (" Izquierda 2,"); break;
		case 4: mov = (" Derecha 2,"); break;
		case 5: mov = (" Izquierda 3,"); break;
		case 6: mov = (" Derecha 3,"); break;		
		default: mov = ("Este movimiento no existe.");
		}		
		camino = (cam + mov);		
	}
	
	/**
	 * Mover hacia la izquierda una posicion, si es posible, el hueco
	 * @return nodo modificado
	 */
	private NodoFichas Izq1(){
		NodoFichas nuevo=null;
		if (x>0){
			nuevo=new NodoFichas(tablero,x,1,camino,this.coste,1,this.profundidad);
			int aux=nuevo.tablero[nuevo.x-1];
			nuevo.tablero[nuevo.x-1]=nuevo.tablero[x];
			nuevo.tablero[nuevo.x]=aux;
			nuevo.x=nuevo.x-1;
			nuevo.vHeur=nuevo.calculavHeur();
			nuevo.calculaEstado();
		}
		return nuevo;
	}
	
	/**
	 * Mover hacia la derecha si es posible una posicion el hueco
	 * @return nodo modificado
	 */
	private NodoFichas Der1(){
		NodoFichas nuevo=null;
		if (x<6){
			nuevo=new NodoFichas(tablero,x,2,camino,this.coste,1,this.profundidad);
			int aux=nuevo.tablero[nuevo.x+1];
			nuevo.tablero[nuevo.x+1]=nuevo.tablero[x];
			nuevo.tablero[nuevo.x]=aux;
			nuevo.x=nuevo.x+1;
			nuevo.vHeur=nuevo.calculavHeur();
			nuevo.calculaEstado();
		}
		return nuevo;
	}
	
	/**
	 * Mover hacia la izquierda si es posible dos posiciones el hueco
	 * @return nodo modificado
	 */
	private NodoFichas Izq2(){
		NodoFichas nuevo=null;
		if (x>1){
			nuevo=new NodoFichas(tablero,x,3,camino,this.coste,2,this.profundidad);
			int aux=nuevo.tablero[nuevo.x-2];
			nuevo.tablero[nuevo.x-2]=nuevo.tablero[x];
			nuevo.tablero[nuevo.x]=aux;
			nuevo.x=nuevo.x-2;
			nuevo.vHeur=nuevo.calculavHeur();
			nuevo.calculaEstado();
		}
		return nuevo;
	}
	
	/**
	 * Mover hacia la derecha si es posible dos posiciones el hueco
	 * @return nodo modificado
	 */
	
	private NodoFichas Der2(){
		NodoFichas nuevo=null;
		if (x<5){
			nuevo=new NodoFichas(tablero,x,4,camino,this.coste,2,this.profundidad);
			int aux=nuevo.tablero[nuevo.x+2];
			nuevo.tablero[nuevo.x+2]=nuevo.tablero[x];
			nuevo.tablero[nuevo.x]=aux;
			nuevo.x=nuevo.x+2;
			nuevo.vHeur=nuevo.calculavHeur();
			nuevo.calculaEstado();
		}
		return nuevo;
	}
	/**
	 * Mover hacia la izquierda si es posible tres posiciones el hueco
	 * @return nodo modificado
	 */
	private NodoFichas Izq3(){
		NodoFichas nuevo=null;
		if (x>2){
			nuevo=new NodoFichas(tablero,x,5,camino,this.coste,3,this.profundidad);
			int aux=nuevo.tablero[nuevo.x-3];
			nuevo.tablero[nuevo.x-3]=nuevo.tablero[x];
			nuevo.tablero[nuevo.x]=aux;
			nuevo.x=nuevo.x-3;
			nuevo.vHeur=nuevo.calculavHeur();
			nuevo.calculaEstado();
		}
		return nuevo;
	}
	/**
	 * Mover hacia la derecha si es posible dos posiciones el hueco
	 * @return nodo modificado
	 */
	private NodoFichas Der3(){
		NodoFichas nuevo=null;
		if (x<4){
			nuevo=new NodoFichas(tablero,x,6,camino,this.coste,3,this.profundidad);
			int aux=nuevo.tablero[nuevo.x+3];
			nuevo.tablero[nuevo.x+3]=nuevo.tablero[x];
			nuevo.tablero[nuevo.x]=aux;
			nuevo.x=nuevo.x+3;
			nuevo.vHeur=nuevo.calculavHeur();
			nuevo.calculaEstado();
			return nuevo;
		}else return nuevo;
	}
	
	/**
	 * Calcula el valor heuristico del nodo
	 * @return el valor del nodo
	 */
	private int calculavHeur(){
		int suma=0;int cont=0;
		for (int j=6;j>-1;j--)
				if (tablero[j]==2) cont=cont+1;
				else if (tablero[j]!=0)suma=cont+suma;
		return suma;
	}
	
	/**
	 * Calcula la heuristica
	 */
	public void calculaHeur(){
		this.vHeur =calculavHeur();
		
	}
	
	/**
	 * Asigna un valor al estado del tablero
	 */
	public void calculaEstado(){
		this.estado = (tablero[0]*1000000) + (tablero[1]*100000) + 
					(tablero[2]*10000) + (tablero[3]*1000) + 
					(tablero[4]*100) + (tablero[5]*10) + 
					(tablero[6]*1);
	}
    
	/**
	 * Calcula si el nodo es final o no
	 * @return true si el nodo es final, false si no
	 */
	public boolean esFinal(){
		return (this.vHeur==0);
    }
   

	/**
	 * Genera todos los hijos del nodo
	 * @return vector con todos los hijos
	 */
	public Vector generaHijos(){
    	Vector nuevo=new Vector(0,1);
    	NodoFichas op1=this.Izq1();
    	NodoFichas op2=this.Der1();
    	NodoFichas op3=this.Izq2();
    	NodoFichas op4=this.Der2();
    	NodoFichas op5=this.Izq3();
    	NodoFichas op6=this.Der3();
    	if (op1!=null) nuevo.addElement(op1);
        if (op2!=null) nuevo.addElement(op2);
      	if (op3!=null) nuevo.addElement(op3);
      	if (op4!=null) nuevo.addElement(op4); 
      	if (op5!=null) nuevo.addElement(op5);
      	if (op6!=null) nuevo.addElement(op6);
        return nuevo;
	} 
}
